package com.ffsky.cordova.app;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;

import com.ffsky.cordova.R;
import com.ffsky.cordova.option.WebOption;
import com.ffsky.cordova.plugin.ExposedJsApiImpl;
import com.ffsky.cordova.util.WebSettingsCompat;
import com.ffsky.jsplugin.ExposedJsApi;
import com.ffsky.jsplugin.JsCallback;
import com.ffsky.jsplugin.JsPlugin;
import com.ffsky.jsplugin.JsPluginCompat;
import com.ffsky.jsplugin.JsPluginManager;
import com.ffsky.litepack.dialog.OnPositiveListener;
import com.ffsky.litepack.dialog.PromptDialog;
import com.ffsky.litepack.toolbar.Toolbar;
import com.ffsky.litepack.util.ActivityUtil;
import com.ffsky.litepack.util.NetworkUtil;
import com.ffsky.litepack.util.StatusBarUtil;
import com.ffsky.litepack.util.StringCompat;
import com.ffsky.logger.L;

import org.apache.cordova.CordovaActivity;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewImpl;
import org.apache.cordova.engine.SystemWebChromeClient;
import org.apache.cordova.engine.SystemWebView;
import org.apache.cordova.engine.SystemWebViewClient;
import org.apache.cordova.engine.SystemWebViewEngine;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class WebActivity extends CordovaActivity {

    private static String APP_TIME_CACHE = "";

    public static void updateTimeCache() {
        APP_TIME_CACHE = makeTimeDay();
    }

    /**
     * 原路返回
     */
    public static final int BACK_MODE_DEFAULT = 1;
    /**
     * 返回页面第一个url地址
     */
    public static final int BACK_MODE_TO_FIRST = 2;
    /**
     * WebView页面销毁
     */
    public static final int BACK_MODE_TO_EXIT = 3;

    /**
     * 页面URL栈大于2个返回第一个
     */
    public static final int BACK_MODE_SIZE_GT_TWO_GOTO_FIRST = 4;

    /**
     * @param activity
     * @param url
     * @param backMode 1=原路返回,2=返回页面第一个url地址,3=WebView页面销毁
     * @param extras
     */
    public static void start(Activity activity, String url, int backMode, Bundle extras) {
        Intent intent = new Intent(activity, WebActivity.class);
        intent.putExtra("__URL", url);
        intent.putExtra("__backMode", backMode);
        if (extras != null) {
            intent.putExtras(extras);
        }
        activity.startActivity(intent);
    }

    public static void startOption(Activity activity, WebOption option) {
        Intent intent = new Intent(activity, WebActivity.class);
        intent.putExtra("__data", option);
        activity.startActivity(intent);
    }

    protected final void buildToolbar(Activity activity) {
        if (mToolbar == null) {
            mToolbar = Toolbar.build(activity);
        }
    }

    public final Toolbar getToolbar() {
        buildToolbar(this);
        return mToolbar;
    }

    final String TAG = "WebActivity";
    private Toolbar mToolbar;
    private SystemWebView mWebView;
    private final List<JsPlugin> jsPluginList = new ArrayList<JsPlugin>();
    private ExposedJsApi mExposedJsApi;
    private WebOption webOption;
    private String firstUrl;
    private String backUrl;
    private View progress_content;

    /**
     * 某些特殊场景,vue路由调整后不希望原来返回
     *
     * @param url
     */
    public void setGoBackUrl(String url) {
        if (!TextUtils.isEmpty(url)) {
            backUrl = url;
        }
    }

    public String getPageData() {
        Intent intent = getIntent();
        return intent.getStringExtra("__pageData");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.lib_activity_web);
        buildToolbar(this);
        super.init();
        initWebView();
        initView();
        Intent intent = getIntent();
        boolean hasOption = getIntent().hasExtra("__data");
        if (hasOption) {
            webOption = intent.getParcelableExtra("__data");
            /**
             * 1=原路返回,2=返回页面第一个url地址,3=WebView页面销毁
             */
            int backMode = intent.getIntExtra("__backMode", 1);
            webOption.backMode = backMode;
        } else {
            final String mUrl = intent.getStringExtra("__URL");
            webOption = new WebOption(mUrl);
            /**
             * 1=原路返回,2=返回页面第一个url地址,3=WebView页面销毁
             */
            int backMode = intent.getIntExtra("__backMode", 1);
            webOption.backMode = backMode;
        }
        webOption.url = buildNewCacheModeUrl(webOption.url);
        setupWebOption();
        firstUrl = webOption.url;
        showLoadProgress();
        if (!TextUtils.isEmpty(webOption.url)) {
            loadUrl(webOption.url);
        } else {
            loadUrl(launchUrl);
        }
    }


    @Override
    protected void onResume() {
        super.onResume();
        if (checkNetworkState()) {
            if (!NetworkUtil.isNetworkConnected(this)) {
                showNetworkErrorDialog(isShowNetworkErrorExit(), Boolean.TRUE);
            }
        }
    }

    protected boolean checkNetworkState() {
        return true;
    }

    protected boolean isShowNetworkErrorExit() {
        return Boolean.TRUE;
    }

    private void setupWebOption() {
        if (webOption.showStatusBar) {
            mToolbar.show();
        } else {
            mToolbar.hide();
        }
        //
        if (webOption.toolbarColor != 0) {
            mToolbar.setBackgroundColor(webOption.toolbarColor);
        }
        if (webOption.showStatusBar) {
            //显示系统状态栏
            if (webOption.statusBarColor != 0) {
                StatusBarUtil.setColor(this, webOption.statusBarColor);
            }
        } else {
            //隐藏系统状态栏-全屏模式
        }
        if (!TextUtils.isEmpty(webOption.title)) {
            mToolbar.setTitle(webOption.title);
        }
        //
    }

    /**
     * 检查url是否为http开头,如果是增加apptime=当天时间,降低WebView缓存HTML引起白屏问题
     *
     * @param url
     * @return
     */
    protected String buildNewCacheModeUrl(String url) {
        String ret = url;
        if (!TextUtils.isEmpty(ret)) {
            String appTime = APP_TIME_CACHE;
            if (url.startsWith("http") && ret.indexOf(".html") > -1) {
                if (ret.indexOf("?") > -1) {
                    ret = StringCompat.string(url, "&apptime=", appTime);
                } else {
                    ret = StringCompat.string(url, "?apptime=", appTime);
                }
            }
        }
        return ret;
    }

    private void initView() {
        progress_content = findViewById(R.id.progress_content);
        mToolbar.setBackOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (goBackUrl()) {
                    return;
                }
                if (onKeyDownAppBack()) {
                    return;
                }
                /**
                 * backMode
                 * 1=原路返回,2=返回页面第一个url地址,3=WebView页面销毁
                 */
                if (webOption.backMode == BACK_MODE_DEFAULT) {
                    if (appView.canGoBack()) {
                        appView.backHistory();
                    } else {
                        finish();
                    }
                    return;
                } else if (webOption.backMode == BACK_MODE_TO_FIRST) {
                    if (!appView.canGoBack()) {
                        finish();
                        return;
                    }
                    backMode2Enable = true;
                    appView.loadUrl(firstUrl);
                } else if (webOption.backMode == BACK_MODE_TO_EXIT) {
                    finish();
                    return;
                } else if (webOption.backMode == BACK_MODE_SIZE_GT_TWO_GOTO_FIRST) {
                    int size = getUrlHistorySize();
                    if (size > 2) {
                        backMode2Enable = true;
                        goBackUrlHistory();
                        appView.loadUrl(firstUrl);
                        return;
                    } else {
                        if (appView.canGoBack()) {
                            appView.backHistory();
                        } else {
                            finish();
                        }
                    }
                }
            }
        });
        initViewDebug();
    }

    private void initWebView() {
        initJsPlugin();
        WebSettingsCompat.settings(mWebView);
        mWebView.setWebViewClient(new SystemWebViewClient((SystemWebViewEngine) appView.getEngine()) {
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                L.i(TAG, "onPageFinished->", url);
                mUrlHistory.add(url);
                //
                JsPluginCompat.onPageFinished(jsPluginList);
                onWebViewPageFinished();
                hideLoadProgress();
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                L.i(TAG, "onPageStarted->", url);
            }

        });

        mExposedJsApi = new ExposedJsApiImpl(appView);
        JsPluginCompat.create(jsPluginList, this, mExposedJsApi);
        //
        WebChromeClient client = new SystemWebChromeClient((SystemWebViewEngine) appView.getEngine()) {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                mWebLoadProgress = newProgress;
                L.i(TAG, "onProgressChanged->", newProgress);
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                if (webOption.updateTitle) {
                    getToolbar().setTitle(title);
                }
                super.onReceivedTitle(view, title);
            }

        };
        mWebView.setWebChromeClient(client);
        mWebView.setDownloadListener((_url, userAgent, contentDisposition, mimetype, contentLength) -> {
            Uri uri = Uri.parse(_url);
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        });
    }

    List<String> mUrlHistory = new ArrayList<>();

    protected void goBackUrlHistory() {
        if (!mUrlHistory.isEmpty()) {
            int size = mUrlHistory.size();
            if (size > -1) {
                mUrlHistory.remove(size - 1);
            }
        }
    }

    protected int getUrlHistorySize() {
        return mUrlHistory.size();
    }

    private int mWebLoadProgress = 0;

    @Override
    public void onReceivedError(int errorCode, String description, String failingUrl) {
        if (errorCode == -6) {
            clearWebViewTimeOut();
            return;
        }
        super.onReceivedError(errorCode, description, failingUrl);
    }

    private void clearWebViewTimeOut() {
        if (mWebLoadProgress == 100) {
            hideLoadProgress();
        }
    }

    private String onBackListener;
    private String onLongBackListener;

    public void setOnBackListener(String listener) {
        onBackListener = listener;
        onLongBackListener = null;
    }

    public void setOnLongBackListener(String longBackListener) {
        onLongBackListener = longBackListener;
        onBackListener = null;
    }

    private boolean onKeyDownAppBack() {
        if (!TextUtils.isEmpty(onLongBackListener)) {
            JsCallback callback = new JsCallback(mExposedJsApi);
            callback.applyMethodName(onLongBackListener, null);
            return true;
        }
        if (!TextUtils.isEmpty(onBackListener)) {
            String jsCall = onBackListener;
            JsCallback callback = new JsCallback(mExposedJsApi);
            callback.applyMethodName(jsCall, null);
            onBackListener = null;
            return true;
        }

        return false;
    }

    protected void showLoadProgress() {
        if (progress_content != null) {
            progress_content.setVisibility(View.VISIBLE);
        }
    }

    protected void hideLoadProgress() {
        if (progress_content != null) {
            progress_content.setVisibility(View.GONE);
        }
    }

    protected void onWebViewPageFinished() {
        if (backMode2Enable) {
            appView.clearHistory();
            backMode2Enable = false;
            mUrlHistory.clear();
        }
    }

    protected void initViewDebug() {

    }

    private void initJsPlugin() {
        if (mWebView != null) {
            if (Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT < 17) {
                mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
            }
        }
        Map<String, Class<? extends JsPlugin>> map = JsPluginManager.getInstance().map();
        if (!map.isEmpty()) {
            Set<String> set = map.keySet();
            for (String key : set) {
                Class<? extends JsPlugin> cls = map.get(key);
                try {
                    JsPlugin jsPlugin = cls.newInstance();
                    jsPluginList.add(jsPlugin);
                    setJavascriptInterface(key, jsPlugin);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }

            }
        }
    }

    private Set<String> regJsList = new HashSet<>();

    private void removeJavascriptInterface() {
        if (mWebView != null) {
            Set<String> set = new HashSet<>(regJsList);
            for (String key : set) {
                if (mWebView != null) {
                    mWebView.removeJavascriptInterface(key);
                }
            }
        }
    }

    @SuppressLint("JavascriptInterface")
    private void setJavascriptInterface(String key, JsPlugin jsPlugin) {
        if (TextUtils.isEmpty(key) || jsPlugin == null) {
            L.e(TAG, "addJavascriptInterface Error.");
            return;
        }
        L.i(TAG, "JsPlugin Name=", key, " Class->", jsPlugin.getClass().getName());
        mWebView.addJavascriptInterface(jsPlugin, key);
        regJsList.add(key);
    }

    @Override
    protected void createViews() {
        appView.getView().requestFocusFromTouch();
    }

    @Override
    protected CordovaWebView makeWebView() {//使用布局中的 webView
        mWebView = findViewById(R.id.cordova_webwiew);
        return new CordovaWebViewImpl(new SystemWebViewEngine(mWebView));
    }

//    @Override
//    public void finish() {
//        this.loadUrl("about:blank");
//        super.finish();
//    }

    public void clearHistory() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if(appView!=null){
                    appView.clearHistory();
                }
            }
        });
    }

    private boolean backMode2Enable = false;

    private boolean goBackUrl() {
        if (!TextUtils.isEmpty(backUrl)) {
            String toUrl = backUrl;
            backMode2Enable = true;
            appView.loadUrl(toUrl);
            backUrl = null;
            return true;
        }
        return false;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (goBackUrl()) {
                return true;
            }
            if (onKeyDownAppBack()) {
                return true;
            }
            /**
             * backMode
             * 1=原路返回,2=返回页面第一个url地址,3=WebView页面销毁
             */
            if (webOption.backMode == BACK_MODE_DEFAULT) {
                if (appView.canGoBack()) {
                    appView.backHistory();
                } else {
                    finish();
                }
                return true;
            } else if (webOption.backMode == BACK_MODE_TO_FIRST) {
                if (!appView.canGoBack()) {
                    finish();
                    return true;
                }
                backMode2Enable = true;
                appView.loadUrl(firstUrl);
                return true;
            } else if (webOption.backMode == BACK_MODE_TO_EXIT) {
                finish();
                return true;
            } else if (webOption.backMode == BACK_MODE_SIZE_GT_TWO_GOTO_FIRST) {
                int size = getUrlHistorySize();
                if (size > 2) {
                    backMode2Enable = true;
                    goBackUrlHistory();
                    appView.loadUrl(firstUrl);
                    return true;
                } else {
                    if (appView.canGoBack()) {
                        appView.backHistory();
                    } else {
                        finish();
                    }
                }
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        JsPluginCompat.onActivityResult(jsPluginList, requestCode, resultCode, intent);
    }

    @Override
    public void onDestroy() {
        removeJavascriptInterface();
        JsPluginCompat.destroy(jsPluginList);
        jsPluginList.clear();
        clearDialog();
        if (mExposedJsApi != null) {
            mExposedJsApi.dispose();
            mExposedJsApi = null;
        }
        super.onDestroy();
    }

    private Dialog mDialog = null;

    public final void clearDialog() {
        if (mDialog != null) {
            if (mDialog.isShowing() && !ActivityUtil.isDestroyed(this)) {
                mDialog.dismiss();
                mDialog = null;
            }
        }
        clearDialogList();
    }

    public void clearDialogList() {

    }

    public final void showNetworkErrorDialog(final boolean exitActivity, boolean ignore) {
        if (!ActivityUtil.isDestroyed(this)) {
            clearDialog();
            PromptDialog _dialog = new PromptDialog(this, 0);
            _dialog.setContentText(R.string.network_error_title);
            _dialog.setCancelable(false);
            _dialog.setPositiveListener(R.string.network_settings, new OnPositiveListener() {
                @Override
                public void onClick(Dialog dialog) {
                    Intent _i = new Intent(Settings.ACTION_WIFI_SETTINGS);
                    startActivity(_i);
                    dialog.dismiss();
                    if (exitActivity) {
                        finish();
                    }
                }
            });
            if (ignore) {
                _dialog.setNegativeListener(R.string.network_settings_ignore, new OnPositiveListener() {
                    @Override
                    public void onClick(Dialog dialog) {
                        dialog.dismiss();
                    }
                });
            }
            _dialog.show();
            _dialog.setupNetWorkListener();
            mDialog = _dialog;
        }
    }


    static String makeTimeDay() {
        Date _date = new Date(System.currentTimeMillis());
        DateFormat datetimeDf = new SimpleDateFormat("yyyyMMdd");
        return datetimeDf.format(_date);
    }

}
